
<!--generated with sswg-->
<style>
    html {max-width: 100%; margin: auto; color: #333333;}
    a.button {padding: 15px 32px; background-color: #555; border-radius: 2em; border-width: 0px; text-decoration: none; color: white; font-size: 25.0px; line-height: 2.5em;}
    a.button:hover {background-color: #777}
    a.button_big {padding: 0.5em; background-image: linear-gradient(to top, #427b0e, #9ba97d); background-color: lightgray; background-blend-mode: multiply; border-radius: .75em; border-width: 0px; text-decoration: none; min-width: 150px; max-width: 150px; min-height: 150px; max-height: 150px; display: inline-block; vertical-align: top; margin: 4px 4px 10px 4px; color: white; font-size: 25.0px; background-size: auto 100%; background-position-x: center;}
    a.button_big:hover {background-color: white; color: #e6d23f; text-decoration: underline;}
    mark {background: #ccff99;}
    span {background-color: rgba(0, 0, 0, 0.55); padding: .1em; line-height: 1.35em;}
    img {max-width: 100%; vertical-align: top;}
    .code_block {background-color: whitesmoke; padding: 10px; margin: 0; font-family: monospace; font-size: 20; font-weight: normal; white-space: pre;}

    purple {color: hsl(289.0, 50%, 50%);}
    gray {color: gray;}
    olive {color: olive;}
    yellow {color: darkgoldenrod;}
    green {color: seagreen;}
    blue {color: hsl(210, 50%, 50%);}

</style>
<html>
<left>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>inventory_tutorial</title>
<br>

<div style="text-align: center;max-width: 1000px; margin: auto;font-family: arial;">
<div style="font-size: 100.0px;font-weight: bold;">
Inventory Tutorial<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
In this tutorial we will make a drag and drop inventory like this.<br>
<br>
<img src="inventory_2.gif"></img> <br>
<br>
<br>
<br>
<div style="text-align: left;">
<div style="font-size: 40.0px;font-weight: bold;">
<div id="1 Setting up the class"/><br>
1 Setting up the class<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;Let's begin by making an Inventory class<br>
<br>
<div class="code_block" style="margin-left: 2em;"><purple>from</purple> ursina <purple>import</purple> *

class Inventory(<olive>Entity</olive>):
    <purple>def</purple> __init__(self):
        super().__init__()



<purple>if</purple> __name__ == <green>'__main__'</green>:
    app = Ursina()
    inventory = Inventory()
    app.run()
</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="2 Adding graphics"/><br>
2 Adding graphics<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;However, if we run the code, we'll see that there's nothing visible.<br>
&nbsp;&nbsp;&nbsp;&nbsp;Let's parent it to the ui and set the model to 'quad', an included model.<br>
<br>
<div class="code_block" style="margin-left: 2em;"><purple>from</purple> ursina <purple>import</purple> *

class Inventory(<olive>Entity</olive>):
    <purple>def</purple> __init__(self):
        super().__init__(
<mark>            parent = camera.ui,                                         </mark>
<mark>            model = <green>'quad'</green>                                              </mark>
            )



<purple>if</purple> __name__ == <green>'__main__'</green>:
    app = Ursina()
    inventory = Inventory()
    app.run()
</div><br>
&nbsp;&nbsp;&nbsp;&nbsp;If we look at it now, we see it's a white square in the middle of the screen.<br>
&nbsp;&nbsp;&nbsp;&nbsp;Let's set it to a nicer shape. We also want (0,0) to be in the upper left corner<br>
&nbsp;&nbsp;&nbsp;&nbsp;because it makes it easier to add items later. Let's also give it a texture and a color.<br>
&nbsp;&nbsp;&nbsp;&nbsp;If we have both, the color value will tint the texture.<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;Now, this is nice and all, but wouldn't it be nice to show a grid as well?<br>
&nbsp;&nbsp;&nbsp;&nbsp;There are multiple way to do that, but in this case, we'll simply make the texture repeat<br>
&nbsp;&nbsp;&nbsp;&nbsp;by setting texture_scale to (5,6). That'll nicely fit the size of our inventory.<br>
<br>
<div class="code_block" style="margin-left: 2em;"><purple>from</purple> ursina <purple>import</purple> *

class Inventory(<olive>Entity</olive>):
    <purple>def</purple> __init__(self):
        super().__init__(
            parent = camera.ui,
            model = <green>'quad'</green>,
<mark>            scale = (.<yellow>5</yellow>, .<yellow>8</yellow>),                                           </mark>
<mark>            origin = (-.<yellow>5</yellow>, .<yellow>5</yellow>),                                         </mark>
<mark>            position = (-.<yellow>3</yellow>,.<yellow>4</yellow>),                                        </mark>
<mark>            texture = <green>'white_cube'</green>,                                     </mark>
<mark>            texture_scale = (<yellow>5</yellow>,<yellow>8</yellow>),                                      </mark>
<mark>            color = color.dark_gray                                     </mark>
            )



<purple>if</purple> __name__ == <green>'__main__'</green>:
    app = Ursina()
    inventory = Inventory()
    app.run()
</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="3 Adding placeholder items"/><br>
3 Adding placeholder items<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;Let's try to add some items to the inventory.<br>
<br>
<div class="code_block" style="margin-left: 2em;"><purple>from</purple> ursina <purple>import</purple> *

class Inventory(<olive>Entity</olive>):
    <purple>def</purple> __init__(self):
        super().__init__(
            parent = camera.ui,
            model = <green>'quad'</green>,
            scale = (.<yellow>5</yellow>, .<yellow>8</yellow>),
            origin = (-.<yellow>5</yellow>, .<yellow>5</yellow>),
            position = (-.<yellow>3</yellow>,.<yellow>4</yellow>),
            texture = <green>'white_cube'</green>,
            texture_scale = (<yellow>5</yellow>,<yellow>8</yellow>),
            color = color.dark_gray
            )



<purple>if</purple> __name__ == <green>'__main__'</green>:
    app = Ursina()
    inventory = Inventory()
<mark>    item = Button(<olive>parent</olive>=inventory, <olive>color</olive>=color.red, <olive>position</olive>=(<yellow>0</yellow>,<yellow>0</yellow>))            </mark>
<mark>    item = Button(<olive>parent</olive>=inventory, <olive>color</olive>=color.green, <olive>position</olive>=(<yellow>2</yellow>,<yellow>0</yellow>))          </mark>
    app.run()
</div><br>
&nbsp;&nbsp;&nbsp;&nbsp;Well, that didn't go as planned. The items cover the entire inventory and<br>
&nbsp;&nbsp;&nbsp;&nbsp;the second item is way off to the left.<br>
&nbsp;&nbsp;&nbsp;&nbsp;Let's fix this by making another object to put the items under.<br>
&nbsp;&nbsp;&nbsp;&nbsp;Scale the object to the size of an item.<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;They also don't fit the grid. Fix that by setting origin to the upper left<br>
&nbsp;&nbsp;&nbsp;&nbsp;corner, (-.5,.5).<br>
<br>
<div class="code_block" style="margin-left: 2em;"><purple>from</purple> ursina <purple>import</purple> *

class Inventory(<olive>Entity</olive>):
    <purple>def</purple> __init__(self):
        super().__init__(
            parent = camera.ui,
            model = <green>'quad'</green>,
            scale = (.<yellow>5</yellow>, .<yellow>8</yellow>),
            origin = (-.<yellow>5</yellow>, .<yellow>5</yellow>),
            position = (-.<yellow>3</yellow>,.<yellow>4</yellow>),
            texture = <green>'white_cube'</green>,
            texture_scale = (<yellow>5</yellow>,<yellow>8</yellow>),
            color = color.dark_gray
            )

<mark>        self.item_parent = <olive>Entity</olive>(<olive>parent</olive>=self, <olive>scale</olive>=(<yellow>1</yellow>/<yellow>5</yellow>,<yellow>1</yellow>/<yellow>8</yellow>))         </mark>



<purple>if</purple> __name__ == <green>'__main__'</green>:
    app = Ursina()
    inventory = Inventory()
<mark>    item = Button(<olive>parent</olive>=inventory.item_parent, <olive>origin</olive>=(-.<yellow>5</yellow>,.<yellow>5</yellow>), <olive>color</olive>=color.red, <olive>position</olive>=(<yellow>0</yellow>,<yellow>0</yellow>))      </mark>
<mark>    item = Button(<olive>parent</olive>=inventory.item_parent, <olive>origin</olive>=(-.<yellow>5</yellow>,.<yellow>5</yellow>), <olive>color</olive>=color.green, <olive>position</olive>=(<yellow>2</yellow>,<yellow>0</yellow>))    </mark>
    app.run()
</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="4 Adding items"/><br>
4 Adding items<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;We've added some items manually to make sure they get the right scale and position,<br>
&nbsp;&nbsp;&nbsp;&nbsp;but we should make an append() function so it's easy to add items.<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;Let's start by making a function called 'append()' and make it spawn an item<br>
&nbsp;&nbsp;&nbsp;&nbsp;when we send it a string. We'll also set the button's text to the string we<br>
&nbsp;&nbsp;&nbsp;&nbsp;receive so we can differentiate them.<br>
&nbsp;&nbsp;&nbsp;&nbsp;Let's give them a random color too, why not.<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;Lastly, let's call inventory.append('test item') a couple of times to make sure it works.<br>
<br>
<br>
<div class="code_block" style="margin-left: 2em;"><purple>from</purple> ursina <purple>import</purple> *

class Inventory(<olive>Entity</olive>):
    <purple>def</purple> __init__(self):
        super().__init__(
            parent = camera.ui,
            model = <green>'quad'</green>,
            scale = (.<yellow>5</yellow>, .<yellow>8</yellow>),
            origin = (-.<yellow>5</yellow>, .<yellow>5</yellow>),
            position = (-.<yellow>3</yellow>,.<yellow>4</yellow>),
            texture = <green>'white_cube'</green>,
            texture_scale = (<yellow>5</yellow>,<yellow>8</yellow>),
            color = color.dark_gray
            )

        self.item_parent = <olive>Entity</olive>(<olive>parent</olive>=self, <olive>scale</olive>=(<yellow>1</yellow>/<yellow>5</yellow>,<yellow>1</yellow>/<yellow>8</yellow>))


<mark>    <purple>def</purple> append(self, item):                                             </mark>
<mark>        Button(                                                         </mark>
<mark>            parent = inventory.item_parent,                             </mark>
<mark>            model = <green>'quad'</green>,                                             </mark>
<mark>            origin = (-.<yellow>5</yellow>,.<yellow>5</yellow>),                                          </mark>
<mark>            color = color.random_color(),                               </mark>
<mark>            z = -.<yellow>1</yellow>                                                     </mark>
            )


<purple>if</purple> __name__ == <green>'__main__'</green>:
    app = Ursina()
    inventory = Inventory()
<mark>    inventory.append(<green>'test item'</green>)                                       </mark>
<mark>    inventory.append(<green>'test item'</green>)                                       </mark>
    app.run()
</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="5 Find a free slot in the inventory"/><br>
5 Find a free slot in the inventory<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;The items gets added, but they overlap. We need to find the first open slot in the inventory<br>
&nbsp;&nbsp;&nbsp;&nbsp;and place the item there. We can to this by checking each grid position and see if any<br>
&nbsp;&nbsp;&nbsp;&nbsp;if the items occupy that position already.<br>
<br>
<div class="code_block" style="margin-left: 2em;"><purple>from</purple> ursina <purple>import</purple> *

class Inventory(<olive>Entity</olive>):
    <purple>def</purple> __init__(self):
        super().__init__(
            parent = camera.ui,
            model = <green>'quad'</green>,
            scale = (.<yellow>5</yellow>, .<yellow>8</yellow>),
            origin = (-.<yellow>5</yellow>, .<yellow>5</yellow>),
            position = (-.<yellow>3</yellow>,.<yellow>4</yellow>),
            texture = <green>'white_cube'</green>,
            texture_scale = (<yellow>5</yellow>,<yellow>8</yellow>),
            color = color.dark_gray
            )

        self.item_parent = <olive>Entity</olive>(<olive>parent</olive>=self, <olive>scale</olive>=(<yellow>1</yellow>/<yellow>5</yellow>,<yellow>1</yellow>/<yellow>8</yellow>))


<mark>    <purple>def</purple> find_free_spot(self):                                                      </mark>
<mark>        taken_spots = [(int(e.x), int(e.y)) <purple>for</purple> e in self.item_parent.children]    </mark>
<mark>        <purple>for</purple> y in <blue>range</blue>(<yellow>8</yellow>):                                                         </mark>
<mark>            <purple>for</purple> x in <blue>range</blue>(<yellow>5</yellow>):                                                     </mark>
<mark>                <purple>if</purple> <purple>not</purple> (x,-y) in taken_spots:                                      </mark>
<mark>                    return (x,-y)                                                  </mark>


    <purple>def</purple> append(self, item):
        Button(
            parent = inventory.item_parent,
            model = <green>'quad'</green>,
            origin = (-.<yellow>5</yellow>,.<yellow>5</yellow>),
            color = color.random_color(),
<mark>            position = self.find_free_spot(),                                       </mark>
            z = -.<yellow>1</yellow>
            )


<purple>if</purple> __name__ == <green>'__main__'</green>:
    app = Ursina()
    inventory = Inventory()
<mark>    <purple>for</purple> i in <blue>range</blue>(<yellow>7</yellow>):                                                  </mark>
<mark>        inventory.append(<green>'test item'</green>)                                   </mark>
    app.run()
</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="6 Add random item button"/><br>
6 Add random item button<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;Make a button to add a random item to the inventory. This is not part of the inventory itself,<br>
&nbsp;&nbsp;&nbsp;&nbsp;but it's useful in order to test it.<br>
&nbsp;&nbsp;&nbsp;&nbsp;Assign the button's 'on_click' to a function, and it will call that function when we click it.<br>
&nbsp;&nbsp;&nbsp;&nbsp;button.on_click = inventory<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;Let's make an tuple with those and make the button choose a random item from the tuple<br>
&nbsp;&nbsp;&nbsp;&nbsp;using random.choice(items)<br>
<br>
<div class="code_block" style="margin-left: 2em;">
<purple>if</purple> __name__ == <green>'__main__'</green>:
    app = Ursina()
    inventory = Inventory()

<mark>    <purple>def</purple> add_item():                                                                  </mark>
<mark>        inventory.append(random.choice((<green>'bag'</green>, <green>'bow_arrow'</green>, <green>'gem'</green>, <green>'orb'</green>, <green>'sword'</green>))) </mark>

<mark>    <purple>for</purple> i in <blue>range</blue>(<yellow>7</yellow>):                                                  </mark>
<mark>        add_item()                                                      </mark>

<mark>    add_item_button = Button(                                           </mark>
<mark>        scale = (.<yellow>1</yellow>,.<yellow>1</yellow>),                                                </mark>
<mark>        x = -.<yellow>5</yellow>,                                                        </mark>
<mark>        color = color.lime.tint(-.<yellow>2</yellow><yellow>5</yellow>),                                  </mark>
<mark>        text = <green>'+'</green>,                                                     </mark>
<mark>        tooltip = Tooltip(<green>'Add random item'</green>),                           </mark>
<mark>        on_click = add_item                                             </mark>
<mark>        )                                                               </mark>

    app.run()
</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="7 Adding textures and hover text"/><br>
7 Adding textures and hover text<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;To add textures, just set texture=item and it will try to find a<br>
&nbsp;&nbsp;&nbsp;&nbsp;texture with that name. It searches first in the project's assets and then<br>
&nbsp;&nbsp;&nbsp;&nbsp;in the assets included with ursina. I've included some icons for the purpose<br>
&nbsp;&nbsp;&nbsp;&nbsp;if this tutorial, but feel free to add your own.<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;Let's also remove the random color and instead show the item's name when we hover it with the mouse.<br>
&nbsp;&nbsp;&nbsp;&nbsp;If a button has 'tooltip' set to something, it will show it when we hover the Button.<br>
<br>
<div class="code_block" style="margin-left: 2em;">    <purple>def</purple> append(self, item):
<mark>        icon = Button(                                                  </mark>
            parent = inventory.item_parent,
            model = <green>'quad'</green>,
<mark>            texture = item,                                             </mark>
<mark>            color = color.white,                                        </mark>
            origin = (-.<yellow>5</yellow>,.<yellow>5</yellow>),
            position = self.find_free_spot(),
            z = -.<yellow>1</yellow>,
            )
<mark>        name = item.replace(<green>'_'</green>, <green>' '</green>).title()                           </mark>
<mark>        icon.tooltip = Tooltip(name)                                    </mark>
<mark>        icon.tooltip.background.color = color.color(<yellow>0</yellow>,<yellow>0</yellow>,<yellow>0</yellow>,.<yellow>8</yellow>)           </mark>

</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="8 Drag n' drop"/><br>
8 Drag n' drop<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;We can't move the items! That's not fun.<br>
&nbsp;&nbsp;&nbsp;&nbsp;However, that's easy to change. Just spawn a Draggable instead of Button.<br>
&nbsp;&nbsp;&nbsp;&nbsp;Draggable inherits from Button, so the tooltips will still work!<br>
<br>
<div class="code_block" style="margin-left: 2em;">    <purple>def</purple> append(self, item):
<mark>        icon = Draggable(                                                   </mark>
            parent = inventory.item_parent,
            model = <green>'quad'</green>,
            texture = item,
            color = color.white,
            origin = (-.<yellow>5</yellow>,.<yellow>5</yellow>),
            position = self.find_free_spot(),
            z = -.<yellow>1</yellow>,
            )
        name = item.replace(<green>'_'</green>, <green>' '</green>).title()
        icon.tooltip = Tooltip(name)
        icon.tooltip.background.color = color.color(<yellow>0</yellow>,<yellow>0</yellow>,<yellow>0</yellow>,.<yellow>8</yellow>)

</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="9 Snap to grid on_drop"/><br>
9 Snap to grid on_drop<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;The items can be moved now, but they don't follow the grid.<br>
&nbsp;&nbsp;&nbsp;&nbsp;Let's round the position when we drop it.<br>
&nbsp;&nbsp;&nbsp;&nbsp;Draggable's will automatically call on_drag() and on_drop() if has them.<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;round the position on drop<br>
<br>
<div class="code_block" style="margin-left: 1em;">    <purple>def</purple> append(self, item):
        icon = Draggable(
            parent = inventory.item_parent,
            model = <green>'quad'</green>,
            texture = item,
            color = color.white,
            origin = (-.<yellow>5</yellow>,.<yellow>5</yellow>),
            position = self.find_free_spot(),
            z = -.<yellow>1</yellow>,
            )
        name = item.replace(<green>'_'</green>, <green>' '</green>).title()
        icon.tooltip = Tooltip(name)
        icon.tooltip.background.color = color.color(<yellow>0</yellow>,<yellow>0</yellow>,<yellow>0</yellow>,.<yellow>8</yellow>)


<mark>        <purple>def</purple> drop():                                                         </mark>
<mark>            icon.x = int(icon.x)                                            </mark>
<mark>            icon.y = int(icon.y)                                            </mark>


<mark>        icon.drop = drop                                                    </mark>

</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="10 Swap items"/><br>
10 Swap items<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;Add a drag function to remember the start position as org_pos.<br>
<br>
<br>
<div class="code_block" style="margin-left: 1em;"><mark>        <purple>def</purple> drag():                                                     </mark>
<mark>            icon.org_pos = (icon.x, icon.y)                             </mark>

        <purple>def</purple> drop():
            icon.x = int(icon.x)
            icon.y = int(icon.y)

            <green><green>''</green></green>'<purple>if</purple> the spot is taken, swap positions<green><green>''</green></green>'
<mark>            <purple>for</purple> c in self.children:                                     </mark>
<mark>                <purple>if</purple> c == icon:                                           </mark>
<mark>                    continue                                            </mark>

<mark>                <purple>if</purple> c.x == icon.x and c.y == icon.y:                     </mark>
<mark>                    <blue>print</blue>(<green>'swap positions'</green>)                             </mark>
<mark>                    c.position = icon.org_pos                           </mark>


<mark>        icon.drag = drag                                                </mark>
        icon.drop = drop

</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="11 Stay inside the inventory, please"/><br>
11 Stay inside the inventory, please<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;We shouldn't be able to drop the items outside of the inventory.<br>
<br>
<div class="code_block" style="margin-left: 1em;">        <purple>def</purple> drop():
            icon.x = int(icon.x)
            icon.y = int(icon.y)

<mark>            <green><green>''</green></green>'<purple>if</purple> outside, return to original position<green><green>''</green></green>'               </mark>
<mark>            <purple>if</purple> icon.x < <yellow>0</yellow> or icon.x >= <yellow>1</yellow> or icon.y > <yellow>0</yellow> or icon.y <= -<yellow>1</yellow>: </mark>
<mark>                icon.position = (icon.org_pos)                          </mark>
<mark>                return                                                  </mark>

            <green><green>''</green></green>'<purple>if</purple> the spot is taken, swap positions<green><green>''</green></green>'
            <purple>for</purple> c in self.children:
                <purple>if</purple> c == icon:
                    continue

                <purple>if</purple> c.x == icon.x and c.y == icon.y:
                    <blue>print</blue>(<green>'swap positions'</green>)
                    c.position = icon.org_pos

        icon.drop = drop

</div><br>
<br>
<br>
<div style="font-size: 40.0px;font-weight: bold;">
<div id="12 Bugfix: Make the dragged items render on top"/><br>
12 Bugfix: Make the dragged items render on top<br>
<div style="font-size: 20.0px;font-weight: normal;">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;All the items are at the same depth, so it hard to say how they will overlap.<br>
&nbsp;&nbsp;&nbsp;&nbsp;It feels natural that the item we're currently dragging stays on top,<br>
&nbsp;&nbsp;&nbsp;&nbsp;so we'll move it back a bit when we drag it and forward when we drop it.<br>
<br>
<div class="code_block" style="margin-left: 1em;">        <purple>def</purple> drag():
            icon.org_pos = (icon.x, icon.y)
<mark>            icon.z -= .<yellow>0</yellow><yellow>1</yellow>   <gray># ensure the dragged item overlaps the rest </mark></gray>

        <purple>def</purple> drop():
            icon.x = int(icon.x)
            icon.y = int(icon.y)
<mark>            icon.z += .<yellow>0</yellow><yellow>1</yellow>                                                </mark>

            <green><green>''</green></green>'<purple>if</purple> outside, return to original position<green><green>''</green></green>'
            <purple>if</purple> icon.x < <yellow>0</yellow> or icon.x >= <yellow>1</yellow> or icon.y > <yellow>0</yellow> or icon.y <= -<yellow>1</yellow>:
                icon.position = (icon.org_pos)
                return

            <green><green>''</green></green>'<purple>if</purple> the spot is taken, swap positions<green><green>''</green></green>'
            <purple>for</purple> c in self.children:
                <purple>if</purple> c == icon:
                    continue

                <purple>if</purple> c.x == icon.x and c.y == icon.y:
                    <blue>print</blue>(<green>'swap positions'</green>)
                    c.position = icon.org_pos

        icon.drag = drag
        icon.drop = drop


</div><br>

</html>